home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 37 / IOPROG_37.ISO / SOFT / Multilizer.exe / disk1 / data1.cab / data1 / [Group9]VCL Source Standard / ivtests.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-12  |  25.2 KB  |  915 lines

  1. unit IvTests;
  2.  
  3. {$I IVMULTI.INC}
  4.  
  5. interface
  6.  
  7. uses
  8. {$IFDEF WIN32}
  9.   Windows,
  10. {$ELSE}
  11.   WinTypes, WinProcs,
  12. {$ENDIF}
  13.   IvDictio;
  14.  
  15. const
  16.   { Expansion Test defaults }
  17.  
  18.   FROM_1_TO_5_C = 200;
  19.   FROM_6_TO_10_C = 100;
  20.   FROM_11_TO_20_C = 70;
  21.   FROM_21_TO_30_C = 50;
  22.   FROM_31_TO_50_C = 30;
  23.   OVER_50_C = 20;
  24.   EXPAND_CHAR_C = '_';
  25.   LAST_EXPAND_CHAR_C = 'X';
  26.   REPLACE_CHAR_C = '.';
  27.  
  28. type
  29.   TIvTestType = (ivttCover, ivttMinimum, ivttCodePage);
  30.  
  31.   TIvTestCode = (ivtcNone, ivtcCover, ivtcMinimum, ivtcSingleByte, ivtcMultibyte,
  32.     ivtcBidirectional);
  33.  
  34.   { TIvTest }
  35.  
  36.   TIvTest = class(TObject)
  37.   protected
  38.     function GetPrimary: Integer; virtual;
  39.     function GetSub: Integer; virtual;
  40.     function GetTestCode: TIvTestCode; virtual;
  41.     function GetName: String; virtual;
  42.     function GetCodePage: Integer; virtual;
  43.     procedure SetCodePage(value: Integer); virtual;
  44.     function GetPureASCII: Boolean; virtual;
  45.  
  46.   public
  47.     function Copy: TIvTest; virtual;
  48.     function Translate(const value: String): String; virtual;
  49.  
  50.     procedure ToLanguage(language: TIvLanguage);
  51.  
  52.     property Name: String read GetName;
  53.     property Primary: Integer read GetPrimary;
  54.     property Sub: Integer read GetSub;
  55.     property TestCode: TIvTestCode read GetTestCode;
  56.     property PureASCII: Boolean read GetPureASCII;
  57.     property CodePage: Integer read GetCodePage write SetCodePage;
  58.   end;
  59.  
  60.   { TIvCoverTest }
  61.  
  62.   TIvCoverTest = class(TIvTest)
  63.   protected
  64.     FReplaceChar: Char;
  65.  
  66.     function GetTestCode: TIvTestCode; override;
  67.     function GetName: String; override;
  68.  
  69.   public
  70.     constructor CreateValue(replaceChar: Char);
  71.  
  72.     function Copy: TIvTest; override;
  73.     function Translate(const value: String): String; override;
  74.  
  75.     property ReplaceChar: Char read FReplaceChar write FReplaceChar;
  76.   end;
  77.  
  78.   { TIvMinimumTest }
  79.  
  80.   TIvMinimumTest = class(TIvTest)
  81.   protected
  82.     FReductionChar: String;
  83.  
  84.     function GetTestCode: TIvTestCode; override;
  85.     function GetName: String; override;
  86.  
  87.   public
  88.     constructor CreateValue(const reductionChar: String);
  89.  
  90.     function Copy: TIvTest; override;
  91.     function Translate(const value: String): String; override;
  92.  
  93.     property ReductionChar: String read FReductionChar write FReductionChar;
  94.   end;
  95.  
  96.   { TIvCodePageTest }
  97.  
  98.   TIvCodePageTest = class(TIvTest)
  99.   protected
  100.     FCodePage: Integer;
  101.  
  102.     function GetCodePage: Integer; override;
  103.     procedure SetCodePage(value: Integer); override;
  104.  
  105.   public
  106.     constructor CreateValue(codePage: Integer);
  107.   end;
  108.  
  109.   { TIvSinglebyteTest }
  110.  
  111.   TIvSinglebyteTestOption = (ivstExpand, ivstEnclose, ivstAlternateCase, ivstUpperCase, ivstDiacritic);
  112.   TIvSinglebyteTestOptions = set of TIvSinglebyteTestOption;
  113.  
  114.   TIvSinglebyteTest = class(TIvCodePageTest)
  115.   protected
  116.     FOptions: TIvSinglebyteTestOptions;
  117.     FFrom1To5: Integer;
  118.     FFrom6To10: Integer;
  119.     FFrom11To20: Integer;
  120.     FFrom21To30: Integer;
  121.     FFrom31To50: Integer;
  122.     FOver50: Integer;
  123.     FExpandChar: Char;
  124.     FLastChar: Char;
  125.  
  126.     function GetTestCode: TIvTestCode; override;
  127.     function GetPrimary: Integer; override;
  128.     function GetName: String; override;
  129.     function GetPureASCII: Boolean; override;
  130.  
  131.   public
  132.     constructor CreateValue(codePage: Integer; options: TIvSinglebyteTestOptions);
  133.     constructor CreateValueEx(codePage: Integer; expand, enclose, alternateCase, upperCase, diacritic: Boolean);
  134.  
  135.     function Copy: TIvTest; override;
  136.     function Translate(const value: String): String; override;
  137.  
  138.     property Options: TIvSinglebyteTestOptions read FOptions write FOptions;
  139.     property From1To5: Integer read FFrom1To5 write FFrom1To5;
  140.     property From6To10: Integer read FFrom6To10 write FFrom6To10;
  141.     property From11To20: Integer read FFrom11To20 write FFrom11To20;
  142.     property From21To30: Integer read FFrom21To30 write FFrom21To30;
  143.     property From31To50: Integer read FFrom31To50 write FFrom31To50;
  144.     property Over50: Integer read FOver50 write FOver50;
  145.     property ExpandChar: Char read FExpandChar write FExpandChar;
  146.     property LastChar: Char read FLastChar write FLastChar;
  147.   end;
  148.  
  149.   { TIvMultibyteTest }
  150.  
  151.   TIvMultibyteTest = class(TIvCodePageTest)
  152.   protected
  153.     FUseDoubleByteChars: Boolean;
  154.  
  155.     function GetTestCode: TIvTestCode; override;
  156.     function GetPrimary: Integer; override;
  157.     function GetSub: Integer; override;
  158.     function GetCodePage: Integer; override;
  159.     function GetName: String; override;
  160.     function GetPureASCII: Boolean; override;
  161.  
  162.   public
  163.     constructor CreateValue(
  164.       codePage: Integer;
  165.       useDoubleByteChars: Boolean);
  166.  
  167.     function Copy: TIvTest; override;
  168.     function Translate(const value: String): String; override;
  169.  
  170.     property UseDoubleByteChars: Boolean read FUseDoubleByteChars write FUseDoubleByteChars;
  171.   end;
  172.  
  173.   { TIvBidirectionalTest }
  174.  
  175.   TIvBidirectionalTest = class(TIvCodePageTest)
  176.   protected
  177.     function GetTestCode: TIvTestCode; override;
  178.     function GetName: String; override;
  179.     function GetPureASCII: Boolean; override;
  180.  
  181.   public
  182.     function Copy: TIvTest; override;
  183.     function Translate(const value: String): String; override;
  184.   end;
  185.  
  186. implementation
  187.  
  188. uses
  189.   SysUtils,
  190.   IvParser;
  191.  
  192. { TIvTest }
  193.  
  194. function TIvTest.GetPrimary: Integer;
  195. begin
  196.   Result := LANG_ENGLISH;
  197. end;
  198.  
  199. function TIvTest.GetSub: Integer;
  200. begin
  201.   Result := 0;
  202. end;
  203.  
  204. function TIvTest.GetTestCode: TIvTestCode;
  205. begin
  206.   Result := ivtcNone;
  207. end;
  208.  
  209. function TIvTest.GetName: String;
  210. begin
  211.   Result := '';
  212. end;
  213.  
  214. function TIvTest.GetPureASCII: Boolean;
  215. begin
  216.   Result := True;
  217. end;
  218.  
  219. function TIvTest.GetCodePage: Integer;
  220. begin
  221.   Result := 0;
  222. end;
  223.  
  224. procedure TIvTest.SetCodePage(value: Integer);
  225. begin
  226. end;
  227.  
  228. function TIvTest.Copy: TIvTest;
  229. begin
  230.   Result := TIvTest.Create;
  231. end;
  232.  
  233. function TIvTest.Translate(const value: String): String;
  234. begin
  235.   Result := value;
  236. end;
  237.  
  238. procedure TIvTest.ToLanguage(language: TIvLanguage);
  239. begin
  240.   language.EnglishName := Name;
  241.   language.NativeName := Name;
  242.   language.Primary := Primary;
  243.   language.DefaultSub := Sub;
  244.   language.Options := [ivloTest];
  245.   if PureASCII then
  246.     language.Options := language.Options + [ivloPureASCII];
  247. end;
  248.  
  249.  
  250. { TIvCoverTest }
  251.  
  252. constructor TIvCoverTest.CreateValue(replaceChar: Char);
  253. begin
  254.   inherited Create;
  255.   FReplaceChar := replaceChar;
  256. end;
  257.  
  258. function TIvCoverTest.Copy: TIvTest;
  259. begin
  260.   Result := TIvCoverTest.CreateValue(FReplaceChar);
  261. end;
  262.  
  263. function TIvCoverTest.GetTestCode: TIvTestCode;
  264. begin
  265.   Result := ivtcCover;
  266. end;
  267.  
  268. function TIvCoverTest.GetName: String;
  269. begin
  270.   Result := 'Test (Cover)';
  271. end;
  272.  
  273. function TIvCoverTest.Translate(const value: String): String;
  274. var
  275.   i: Integer;
  276. begin
  277.   Result := value;
  278.   for i := 1 to Length(value) do
  279.     Result[i] := FReplaceChar;
  280. end;
  281.  
  282.  
  283. { TIvMinimumTest }
  284.  
  285. constructor TIvMinimumTest.CreateValue(const reductionChar: String);
  286. begin
  287.   inherited Create;
  288.   FReductionChar := reductionChar;
  289. end;
  290.  
  291. function TIvMinimumTest.Copy: TIvTest;
  292. begin
  293.   Result := TIvMinimumTest.CreateValue(FReductionChar);
  294. end;
  295.  
  296. function TIvMinimumTest.GetTestCode: TIvTestCode;
  297. begin
  298.   Result := ivtcMinimum;
  299. end;
  300.  
  301. function TIvMinimumTest.GetName: String;
  302. begin
  303.   Result := 'Test (Minimum)';
  304. end;
  305.  
  306. function TIvMinimumTest.Translate(const value: String): String;
  307. begin
  308.   if value = '' then
  309.     Result := ''
  310.   else if FReductionChar <> '' then
  311.     Result := FReductionChar
  312.   else if (value[1] = '&') and (Length(value) > 1) then
  313.     Result := value[2]
  314.   else
  315.     Result := value[1];
  316. end;
  317.  
  318.  
  319. { TIvCodePageTest }
  320.  
  321. constructor TIvCodePageTest.CreateValue(codePage: Integer);
  322. begin
  323.   inherited Create;
  324.   FCodePage := codePage;
  325. end;
  326.  
  327. function TIvCodePageTest.GetCodePage: Integer;
  328. begin
  329.   Result := FCodePage;
  330. end;
  331.  
  332. procedure TIvCodePageTest.SetCodePage(value: Integer);
  333. begin
  334.   FCodePage := value;
  335. end;
  336.  
  337.  
  338. { TIvSinglebyteTest }
  339.  
  340. constructor TIvSinglebyteTest.CreateValue(codePage: Integer; options: TIvSinglebyteTestOptions);
  341. begin
  342.   inherited CreateValue(codePage);
  343.   FOptions := options;
  344.   FFrom1To5 := FROM_1_TO_5_C;
  345.   FFrom6To10 := FROM_6_TO_10_C;
  346.   FFrom11To20 := FROM_11_TO_20_C;
  347.   FFrom21To30 := FROM_21_TO_30_C;
  348.   FFrom31To50 := FROM_31_TO_50_C;
  349.   FOver50 := OVER_50_C;
  350.   FExpandChar := EXPAND_CHAR_C;
  351.   FLastChar := LAST_EXPAND_CHAR_C;
  352. end;
  353.  
  354. constructor TIvSinglebyteTest.CreateValueEx(codePage: Integer; expand, enclose, alternateCase, upperCase, diacritic: Boolean);
  355. var
  356.   options: TIvSinglebyteTestOptions;
  357. begin
  358.   options := [];
  359.  
  360.   if expand then
  361.     options := options + [ivstExpand];
  362.  
  363.   if enclose then
  364.     options := options + [ivstEnclose];
  365.  
  366.   if alternateCase then
  367.     options := options + [ivstAlternateCase];
  368.  
  369.   if upperCase then
  370.     options := options + [ivstUpperCase];
  371.  
  372.   if diacritic then
  373.     options := options + [ivstDiacritic];
  374.  
  375.   CreateValue(codePage, options);
  376. end;
  377.  
  378. function TIvSinglebyteTest.GetPureASCII: Boolean;
  379. begin
  380.   Result := not (ivstDiacritic in FOptions);
  381. end;
  382.  
  383. function TIvSinglebyteTest.Copy: TIvTest;
  384. var
  385.   test: TIvSinglebyteTest;
  386. begin
  387.   test := TIvSinglebyteTest.CreateValue(FCodePage, FOptions);
  388.   test.FFrom1To5 := FFrom1To5;
  389.   test.FFrom6To10 := FFrom6To10;
  390.   test.FFrom11To20 := FFrom11To20;
  391.   test.FFrom21To30 := FFrom21To30;
  392.   test.FFrom31To50 := FFrom31To50;
  393.   test.FOver50 := FOver50;
  394.   test.FExpandChar := FExpandChar;
  395.   test.FLastChar := FLastChar;
  396.   Result := test;
  397. end;
  398.  
  399. function TIvSinglebyteTest.GetPrimary: Integer;
  400. begin
  401.   if ivstDiacritic in FOptions then
  402.     Result := LANG_FINNISH
  403.   else
  404.     Result := LANG_ENGLISH;
  405. end;
  406.  
  407. function TIvSinglebyteTest.GetTestCode: TIvTestCode;
  408. begin
  409.   Result := ivtcSinglebyte;
  410. end;
  411.  
  412. function TIvSinglebyteTest.GetName: String;
  413. begin
  414.   Result := 'Test (Singlebyte)';
  415. end;
  416.  
  417. function TIvSinglebyteTest.Translate(const value: String): String;
  418.  
  419.   procedure AlternateCase(var str: String);
  420.   var
  421.     i: Integer;
  422.   begin
  423.     for i := 1 to Length(str) do
  424.     begin
  425.       if (i mod 2) = 0 then
  426.         str[i] := AnsiLowerCase(str[i])[1]
  427.       else
  428.         str[i] := AnsiUpperCase(str[i])[1];
  429.     end;
  430.   end;
  431.  
  432.   procedure AddBalticDiacritics(var str: String);
  433.   var
  434.     i: Integer;
  435.   begin
  436.     for i := 1 to Length(str) do
  437.     begin
  438.     end;
  439.   end;
  440.  
  441.   procedure AddEastEuropeDiacritics(var str: String);
  442.   var
  443.     i: Integer;
  444.   begin
  445.     for i := 1 to Length(str) do
  446.     begin
  447.       case str[i] of
  448.         'a': str[i] := Chr(228);
  449.         'A': str[i] := Chr(196);
  450.         'e': str[i] := Chr(234);
  451.         'E': str[i] := Chr(202);
  452.         'i': str[i] := Chr(238);
  453.         'I': str[i] := Chr(206);
  454.         'o': str[i] := Chr(246);
  455.         'O': str[i] := Chr(214);
  456.         'u': str[i] := Chr(250);
  457.         'U': str[i] := Chr(218);
  458.         'y': str[i] := Chr(253);
  459.         'Y': str[i] := Chr(221);
  460.       end;
  461.     end;
  462.   end;
  463.  
  464.   procedure ConvertToCyrillic(var str: String);
  465.   var
  466.     i: Integer;
  467.   begin
  468.     for i := 1 to Length(str) do
  469.     begin
  470.       if (str[i] >= 'a') and (str[i] <= 'z') then
  471.         str[i] := Chr(224 + Ord(str[i]) - Ord('a'))
  472.       else if (str[i] >= 'A') and (str[i] <= 'Z') then
  473.         str[i] := Chr(192 + Ord(str[i]) - Ord('A'));
  474.     end;
  475.   end;
  476.  
  477.   procedure ConvertToGreek(var str: String);
  478.   var
  479.     i: Integer;
  480.   begin
  481.     for i := 1 to Length(str) do
  482.     begin
  483.       if (str[i] >= 'a') and (str[i] <= 'z') then
  484.         str[i] := Chr(225 + Ord(str[i]) - Ord('a'))
  485.       else if (str[i] >= 'A') and (str[i] <= 'Z') then
  486.         str[i] := Chr(193 + Ord(str[i]) - Ord('A'));
  487.     end;
  488.   end;
  489.  
  490.   procedure AddTurkishDiacritics(var str: String);
  491.   var
  492.     i: Integer;
  493.   begin
  494.     for i := 1 to Length(str) do
  495.     begin
  496.     end;
  497.   end;
  498.  
  499.   procedure AddWesternDiacritics(var str: String);
  500.   var
  501.     i: Integer;
  502.   begin
  503.     for i := 1 to Length(str) do
  504.       case str[i] of
  505.         'a': str[i] := 'Σ';
  506.         'A': str[i] := '─';
  507.         'e': str[i] := 'Ω';
  508.         'E': str[i] := '╩';
  509.         'i': str[i] := '∩';
  510.         'I': str[i] := '╧';
  511.         'o': str[i] := '÷';
  512.         'O': str[i] := '╓';
  513.         'u': str[i] := 'ⁿ';
  514.         'U': str[i] := '▄';
  515.         'y': str[i] := ' ';
  516.         'Y': str[i] := 'ƒ';
  517. {
  518.         'c': str[i] := 'τ';
  519.         'C': str[i] := '╟';
  520.         'd': str[i] := '≡';
  521.         'D': str[i] := '╨';
  522.         'n': str[i] := '±';
  523.         'N': str[i] := '╤';
  524.         's': str[i] := 'Ü';
  525.         'S': str[i] := 'è';
  526. }
  527.       end;
  528.   end;
  529.  
  530.   procedure Expand(var str: String);
  531.   var
  532.     i, len, newLen: Integer;
  533.   begin
  534.     len := Length(str);
  535.     if len <= 5 then
  536.       newLen := len + FFrom1To5*len div 100
  537.     else if len <= 10 then
  538.       newLen := len + FFrom6To10*len div 100
  539.     else if len <= 20 then
  540.       newLen := len + FFrom11To20*len div 100
  541.     else if len <= 30 then
  542.       newLen := len + FFrom21To30*len div 100
  543.     else if len <= 50 then
  544.       newLen := len + FFrom31To50*len div 100
  545.     else
  546.       newLen := len + FOver50*len div 100;
  547.  
  548.     if ivstEnclose in FOptions then
  549.       Dec(newLen, 2);
  550.  
  551.     for i := len to newLen - 2 do
  552.       str := str + FExpandChar;
  553.     str := str + FLastChar;
  554.   end;
  555.  
  556.   procedure Enclose(var str: String);
  557.   begin
  558.     str := '{' + str + '}';
  559.   end;
  560.  
  561. begin
  562.   Result := value;
  563.  
  564.   if ivstAlternateCase in FOptions then
  565.     AlternateCase(Result);
  566.  
  567.   if ivstUpperCase in FOptions then
  568.     Result := UpperCase(Result);
  569.  
  570.   if (ivstDiacritic in FOptions) or (CodePage = CYRILLIC_CP_C) or (CodePage = GREEK_CP_C) then
  571.   begin
  572.     case CodePage of
  573.       BALTIC_CP_C: AddBalticDiacritics(Result);
  574.       EAST_EUROPE_CP_C: AddEastEuropeDiacritics(Result);
  575.       CYRILLIC_CP_C: ConvertToCyrillic(Result);
  576.       GREEK_CP_C: ConvertToGreek(Result);
  577.       TURKISH_CP_C: AddTurkishDiacritics(Result);
  578.       WESTERN_CP_C: AddWesternDiacritics(Result);
  579.     end;
  580.   end;
  581.  
  582.   if ivstExpand in FOptions then
  583.     Expand(Result);
  584.  
  585.   if ivstEnclose in FOptions then
  586.     Enclose(Result);
  587. end;
  588.  
  589.  
  590. { TIvMultibyteTest }
  591.  
  592. constructor TIvMultibyteTest.CreateValue(
  593.   codePage: Integer;
  594.   useDoubleByteChars: Boolean);
  595. begin
  596.   inherited CreateValue(codePage);
  597.   FUseDoubleByteChars := useDoubleByteChars;
  598. end;
  599.  
  600. function TIvMultibyteTest.Copy: TIvTest;
  601. begin
  602.   Result := TIvMultibyteTest.CreateValue(CodePage, FUseDoubleByteChars);
  603. end;
  604.  
  605. function TIvMultibyteTest.GetPureASCII: Boolean;
  606. begin
  607.   Result := not FUseDoubleByteChars;
  608. end;
  609.  
  610. function TIvMultibyteTest.GetPrimary: Integer;
  611. begin
  612.   Result := inherited GetPrimary;
  613.   if FUseDoubleByteChars then
  614.     case CodePage of
  615.       SIMPLIFIED_CHINESE_CP_C: Result := LANG_CHINESE;
  616.       TRADITIONAL_CHINESE_CP_C: Result := LANG_CHINESE;
  617.       JAPANESE_CP_C: Result := LANG_JAPANESE;
  618.       KOREAN_CP_C: Result := LANG_KOREAN;
  619.     end
  620. end;
  621.  
  622. function TIvMultibyteTest.GetSub: Integer;
  623. begin
  624.   Result := inherited GetSub;
  625.   if FUseDoubleByteChars then
  626.     case CodePage of
  627.       SIMPLIFIED_CHINESE_CP_C: Result := SUBLANG_CHINESE_SIMPLIFIED or SUBLANG_CHINESE_SINGAPORE;
  628.       TRADITIONAL_CHINESE_CP_C: Result := SUBLANG_CHINESE_TRADITIONAL or SUBLANG_CHINESE_HONGKONG;
  629.     end
  630. end;
  631.  
  632. function TIvMultibyteTest.GetCodePage: Integer;
  633. begin
  634.   if FUseDoubleByteChars then
  635.     Result := FCodePage
  636.   else
  637.     Result := inherited GetCodePage;
  638. end;
  639.  
  640. function TIvMultibyteTest.GetTestCode: TIvTestCode;
  641. begin
  642.   Result := ivtcMultibyte;
  643. end;
  644.  
  645. function TIvMultibyteTest.GetName: String;
  646. begin
  647.   if FUseDoubleByteChars then
  648.     case CodePage of
  649.       SIMPLIFIED_CHINESE_CP_C: Result := 'Test (Simplified Chinese)';
  650.       TRADITIONAL_CHINESE_CP_C: Result := 'Test (Traditional Chinese)';
  651.       JAPANESE_CP_C: Result := 'Test (Japanese)';
  652.       KOREAN_CP_C: Result := 'Test (Korean)';
  653.     end
  654.   else
  655.     Result := 'Test (Multibyte)';
  656. end;
  657.  
  658. function TIvMultibyteTest.Translate(const value: String): String;
  659.  
  660.   function ConvertToJapanese(const str: String): String;
  661.   var
  662.     i: Integer;
  663.   begin
  664.     Result := '';
  665.     for i := 1 to Length(str) do
  666.     begin
  667.       if (str[i] >= '0') and (str[i] <= '9') then
  668.         Result := Result + Chr($82) + Chr($4F + Ord(str[i]) - Ord('0'))
  669.       else if (str[i] >= 'a') and (str[i] <= 'z') then
  670.         Result := Result + Chr($82) + Chr($81 + Ord(str[i]) - Ord('a'))
  671.       else if (str[i] >= 'A') and (str[i] <= 'Z') then
  672.         Result := Result + Chr($82) + Chr($60 + Ord(str[i]) - Ord('A'))
  673.       else
  674.         case str[i] of
  675.           ' ': Result := Result + ' ';
  676.           '!': Result := Result + Chr($81) + Chr($49);
  677.           '"': Result := Result + Chr($81) + Chr($8D);
  678.           '#': Result := Result + Chr($81) + Chr($94);
  679.           '$': Result := Result + Chr($81) + Chr($90);
  680.           '%': Result := Result + Chr($81) + Chr($93);
  681.           '&': Result := Result + Chr($81) + Chr($95);
  682.           '''': Result := Result + Chr($81) + Chr($8C);
  683.           '(': Result := Result + Chr($81) + Chr($69);
  684.           ')': Result := Result + Chr($81) + Chr($6A);
  685.           '*': Result := Result + Chr($81) + Chr($96);
  686.           '+': Result := Result + Chr($81) + Chr($7B);
  687.           ',': Result := Result + Chr($81) + Chr($43);
  688.           '-': Result := Result + Chr($81) + Chr($7C);
  689.           '.': Result := Result + Chr($81) + Chr($44);
  690.           '/': Result := Result + Chr($81) + Chr($5E);
  691.           ':': Result := Result + Chr($81) + Chr($46);
  692.           ';': Result := Result + Chr($81) + Chr($47);
  693.           '<': Result := Result + Chr($81) + Chr($71);
  694.           '=': Result := Result + Chr($81) + Chr($81);
  695.           '>': Result := Result + Chr($81) + Chr($72);
  696.           '?': Result := Result + Chr($81) + Chr($48);
  697.           '@': Result := Result + Chr($81) + Chr($97);
  698.           '[': Result := Result + Chr($81) + Chr($6D);
  699.           '\': Result := Result + Chr($81) + Chr($5F);
  700.           ']': Result := Result + Chr($81) + Chr($6E);
  701.           '^': Result := Result + Chr($81) + Chr($4F);
  702.           '_': Result := Result + Chr($81) + Chr($51);
  703.           '`': Result := Result + Chr($81) + Chr($4D);
  704.           '{': Result := Result + Chr($81) + Chr($6F);
  705.           '|': Result := Result + Chr($81) + Chr($62);
  706.           '}': Result := Result + Chr($81) + Chr($70);
  707.           '~': Result := Result + Chr($81) + Chr($60);
  708.         else
  709.           Result := Result + str[i];
  710.         end;
  711.     end;
  712.   end;
  713.  
  714.   function ConvertToKorean(const str: String): String;
  715.   var
  716.     i: Integer;
  717.   begin
  718.     Result := '';
  719.     for i := 1 to Length(str) do
  720.     begin
  721.       if (str[i] >= '0') and (str[i] <= '9') then
  722.         Result := Result + Chr($A3) + Chr($B0 + Ord(str[i]) - Ord('0'))
  723.       else if (str[i] >= 'a') and (str[i] <= 'z') then
  724.         Result := Result + Chr($A3) + Chr($E1 + Ord(str[i]) - Ord('a'))
  725.       else if (str[i] >= 'A') and (str[i] <= 'Z') then
  726.         Result := Result + Chr($A3) + Chr($C1 + Ord(str[i]) - Ord('A'))
  727.       else
  728.         case str[i] of
  729.           ' ': Result := Result + Chr($A1) + Chr($A1);
  730.           '!': Result := Result + Chr($A3) + Chr($A1);
  731.           '"': Result := Result + Chr($A3) + Chr($A2);
  732.           '#': Result := Result + Chr($A3) + Chr($A3);
  733.           '$': Result := Result + Chr($A3) + Chr($A4);
  734.           '%': Result := Result + Chr($A3) + Chr($A5);
  735.           '&': Result := Result + Chr($A3) + Chr($A6);
  736.           '''': Result := Result + Chr($A3) + Chr($A7);
  737.           '(': Result := Result + Chr($A3) + Chr($A8);
  738.           ')': Result := Result + Chr($A3) + Chr($A9);
  739.           '*': Result := Result + Chr($A3) + Chr($AA);
  740.           '+': Result := Result + Chr($A3) + Chr($AB);
  741.           ',': Result := Result + Chr($A3) + Chr($AC);
  742.           '-': Result := Result + Chr($A3) + Chr($AD);
  743.           '.': Result := Result + Chr($A3) + Chr($AE);
  744.           '/': Result := Result + Chr($A3) + Chr($AF);
  745.  
  746.           ':': Result := Result + Chr($A3) + Chr($BA);
  747.           ';': Result := Result + Chr($A3) + Chr($BB);
  748.           '<': Result := Result + Chr($A3) + Chr($BC);
  749.           '=': Result := Result + Chr($A3) + Chr($BD);
  750.           '>': Result := Result + Chr($A3) + Chr($BE);
  751.           '?': Result := Result + Chr($A3) + Chr($BF);
  752.  
  753.           '@': Result := Result + Chr($A3) + Chr($C0);
  754.  
  755.           '[': Result := Result + Chr($A3) + Chr($DB);
  756.           '\': Result := Result + Chr($A3) + Chr($DC);
  757.           ']': Result := Result + Chr($A3) + Chr($DD);
  758.           '^': Result := Result + Chr($A3) + Chr($DE);
  759.           '_': Result := Result + Chr($A3) + Chr($DF);
  760.  
  761.           '`': Result := Result + Chr($A3) + Chr($E0);
  762.  
  763.           '{': Result := Result + Chr($A3) + Chr($FB);
  764.           '|': Result := Result + Chr($A3) + Chr($FC);
  765.           '}': Result := Result + Chr($A3) + Chr($FD);
  766.           '~': Result := Result + Chr($A3) + Chr($FE);
  767.         else
  768.           Result := Result + str[i];
  769.         end;
  770.     end;
  771.   end;
  772.  
  773.   function ConvertToSimplifiedChinese(const str: String): String;
  774.   begin
  775.     { Simplified Chinese uses the same codes as Korean to code double byte ASCII }
  776.  
  777.     Result := ConvertToKorean(str);
  778.   end;
  779.  
  780.   function ConvertToTraditionalChinese(const str: String): String;
  781.   var
  782.     i: Integer;
  783.   begin
  784.     Result := '';
  785.     for i := 1 to Length(str) do
  786.     begin
  787.       if (str[i] >= '0') and (str[i] <= '9') then
  788.         Result := Result + Chr($A2) + Chr($AF + Ord(str[i]) - Ord('0'))
  789.       else if (str[i] >= 'a') and (str[i] <= 'z') then
  790.         Result := Result + Chr($A2) + Chr($E9 + Ord(str[i]) - Ord('a'))
  791.       else if (str[i] >= 'A') and (str[i] <= 'Z') then
  792.         Result := Result + Chr($A2) + Chr($CF + Ord(str[i]) - Ord('A'))
  793.       else
  794.         case str[i] of
  795.           ' ': Result := Result + Chr($A1) + Chr($40);
  796.           '!': Result := Result + Chr($A1) + Chr($54);
  797.           '"': Result := Result + Chr($A1) + Chr($A7);
  798.           '#': Result := Result + Chr($A1) + Chr($AD);
  799.           '$': Result := Result + Chr($A2) + Chr($43);
  800.           '%': Result := Result + Chr($A2) + Chr($48);
  801.           '&': Result := Result + Chr($A1) + Chr($AE);
  802.           '''': Result := Result + Chr($A1) + Chr($41);
  803.           '(': Result := Result + Chr($A1) + Chr($5D);
  804.           ')': Result := Result + Chr($A1) + Chr($5E);
  805.           '*': Result := Result + Chr($A1) + Chr($AF);
  806.           '+': Result := Result + Chr($A1) + Chr($CF);
  807.           ',': Result := Result + Chr($A1) + Chr($4D);
  808.           '-': Result := Result + Chr($A1) + Chr($DF);
  809.           '.': Result := Result + Chr($A1) + Chr($4F);
  810.           '/': Result := Result + Chr($A2) + Chr($41);
  811.           ':': Result := Result + Chr($A1) + Chr($47);
  812.           ';': Result := Result + Chr($A1) + Chr($46);
  813.           '<': Result := Result + Chr($A1) + Chr($D5);
  814.           '=': Result := Result + Chr($A1) + Chr($D7);
  815.           '>': Result := Result + Chr($A1) + Chr($D6);
  816.           '?': Result := Result + Chr($A1) + Chr($48);
  817.           '@': Result := Result + Chr($A2) + Chr($4E);
  818.           '[': Result := Result + Chr($A1) + Chr($A3);
  819.           '\': Result := Result + Chr($A2) + Chr($42);
  820.           ']': Result := Result + Chr($A1) + Chr($A4);
  821.           '^': Result := Result + Chr($A1) + Chr($6F);
  822.           '_': Result := Result + Chr($A1) + Chr($C5);
  823.           '`': Result := Result + Chr($A1) + Chr($42);
  824.           '{': Result := Result + Chr($A1) + Chr($A1);
  825.           '|': Result := Result + Chr($A1) + Chr($55);
  826.           '}': Result := Result + Chr($A1) + Chr($A2);
  827.           '~': Result := Result + Chr($A1) + Chr($5C);
  828.         else
  829.           Result := Result + str[i];
  830.         end;
  831.     end;
  832.   end;
  833.  
  834. begin
  835.   if FUseDoubleByteChars then
  836.     case CodePage of
  837.       SIMPLIFIED_CHINESE_CP_C: Result := ConvertToSimplifiedChinese(value);
  838.       TRADITIONAL_CHINESE_CP_C: Result := ConvertToTraditionalChinese(value);
  839.       JAPANESE_CP_C: Result := ConvertToJapanese(value);
  840.       KOREAN_CP_C: Result := ConvertToKorean(value);
  841.     else
  842.       Result := value;
  843.     end
  844.   else
  845.     Result := value;
  846. end;
  847.  
  848.  
  849. { TIvBidirectionalTest }
  850.  
  851. function TIvBidirectionalTest.Copy: TIvTest;
  852. begin
  853.   Result := TIvBidirectionalTest.Create;
  854. end;
  855.  
  856. function TIvBidirectionalTest.GetTestCode: TIvTestCode;
  857. begin
  858.   Result := ivtcBidirectional;
  859. end;
  860.  
  861. function TIvBidirectionalTest.GetName: String;
  862. begin
  863.   Result := 'Test (Bidirectional)';
  864. end;
  865.  
  866. function TIvBidirectionalTest.GetPureASCII: Boolean;
  867. begin
  868.   Result := False;
  869. end;
  870.  
  871. function TIvBidirectionalTest.Translate(const value: String): String;
  872.  
  873.   function ConvertToArabic(const str: String): String;
  874.   var
  875.     i: Integer;
  876.   begin
  877.     Result := '';
  878.     for i := 1 to Length(str) do
  879.     begin
  880.       if (str[i] >= 'a') and (str[i] <= 'z') then
  881.         Result := Result + Chr($C1 + Ord(str[i]) - Ord('a'))
  882.       else if (str[i] >= 'A') and (str[i] <= 'Z') then
  883.         Result := Result + Chr($C1 + Ord(str[i]) - Ord('A'))
  884.       else
  885.         Result := Result + str[i];
  886.     end;
  887.   end;
  888.  
  889.   function ConvertToHebrew(const str: String): String;
  890.   var
  891.     i: Integer;
  892.   begin
  893.     Result := '';
  894.     for i := 1 to Length(str) do
  895.     begin
  896.       if (str[i] >= 'a') and (str[i] <= 'z') then
  897.         Result := Result + Chr($E0 + Ord(str[i]) - Ord('a'))
  898.       else if (str[i] >= 'A') and (str[i] <= 'Z') then
  899.         Result := Result + Chr($E0 + Ord(str[i]) - Ord('A'))
  900.       else
  901.         Result := Result + str[i];
  902.     end;
  903.   end;
  904.  
  905. begin
  906.   case CodePage of
  907.     ARABIC_CP_C: Result := ConvertToArabic(value);
  908.     HEBREW_CP_C: Result := ConvertToHebrew(value);
  909.   else
  910.     Result := value;
  911.   end
  912. end;
  913.  
  914. end.
  915.